﻿using Bikiball.Game;
using SharpDX;
using SharpDX.Toolkit.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bikiball.Graphic.Constructor
{
    public static class Map2DConstructor
    {
        public static Texture2D MapTexture = null;
        public static Effect MapEffect = null;

        public static void LoadContent()
        {
            MapTexture = GraphicEngine.Content.Load<Texture2D>("map2D.dds");
            MapEffect = new BasicEffect(GraphicEngine.GraphicsDevice)
            {
                TextureEnabled = true,
                View = Matrix.LookAtLH(new Vector3(0.0001f, -5, -5), new Vector3(0, 0, 0), Vector3.UnitY),
                Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, (float)(GraphicEngine.GraphicsDevice.BackBuffer).Width / (GraphicEngine.GraphicsDevice.BackBuffer).Height, 0.1f, 100.0f),
                World = Matrix.Zero
            };
        }
        public static GraphicProperty Construct(Map map)
        {
            GraphicProperty gp = new GraphicProperty();
            // Creates a basic effect
            /* gp.Effect = new BasicEffect(GraphicEngine.GraphicsDevice)
             {
                 VertexColorEnabled = true,
                 View = Matrix.LookAtLH(new Vector3(0.0001f, -5, -5), new Vector3(0, 0, 0), Vector3.UnitY),
                 Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, (float)(GraphicEngine.GraphicsDevice.BackBuffer).Width / (GraphicEngine.GraphicsDevice.BackBuffer).Height, 0.1f, 100.0f),
                 World = Matrix.Zero
             };*/
            SetNbVertices(gp, map);
            int[] indices = new int[gp.NumIndices];
            VertexPositionTexture[] vertices = new VertexPositionTexture[gp.NumVertices];
            int i = 0;
            int v = 0;
            for (int x = 0; x < map.SizeX; x++)
            {
                for (int y = 0; y < map.SizeY; y++)
                {
                    for (int z = 0; z < map.SizeZ; z++)
                    {
                        float imageLayer = ((int)map.MapCases[x, y, z] * 8.0f - 4.0f) / 256.0f;
                        switch (map.MapCases[x, y, z])
                        {
                            case MapCase.Empty:
                                break;
                            case MapCase.Wall:
                                // Bottom Vertexes
                                vertices[v] = new VertexPositionTexture(new Vector3(x + 1, y, z), new Vector2(0.0f, 1.0f));
                                vertices[v + 1] = new VertexPositionTexture(new Vector3(x + 1, y + 1, z), new Vector2(0.0f, 0.0f));
                                vertices[v + 2] = new VertexPositionTexture(new Vector3(x + 1, y, z + 1), new Vector2(1.0f, 1.0f));
                                vertices[v + 3] = new VertexPositionTexture(new Vector3(x + 1, y + 1, z + 1), new Vector2(1.0f, 0.0f));
                                // Top Vertexes
                                vertices[v + 4] = new VertexPositionTexture(new Vector3(x, y, z + 1), new Vector2(0.0f, 1.0f));
                                vertices[v + 5] = new VertexPositionTexture(new Vector3(x, y, z), new Vector2(1.0f, 1.0f));
                                vertices[v + 6] = new VertexPositionTexture(new Vector3(x, y + 1, z + 1), new Vector2(0.0f, 0.0f));
                                vertices[v + 7] = new VertexPositionTexture(new Vector3(x, y + 1, z), new Vector2(1.0f, 0.0f));
                                //Face Devant
                                indices[i] = v + 4; indices[i + 1] = (v + 6); indices[i + 2] = (v + 2);
                                indices[i + 3] = (v + 3); indices[i + 4] = v + 2; indices[i + 5] = (v + 6);
                                //Face Derrière

                                indices[i + 6] = v + 7; indices[i + 7] = v + 5; indices[i + 8] = v;
                                indices[i + 9] = v + 7; indices[i + 10] = v; indices[i + 11] = v + 1;
                                //Face Gauche
                                indices[i + 12] = v + 5; indices[i + 13] = (v + 6); indices[i + 14] = (v + 4);
                                indices[i + 15] = (v + 6); indices[i + 16] = v + 5; indices[i + 17] = (v + 7);
                                //Face Droite
                                indices[i + 18] = v; indices[i + 19] = (v + 2); indices[i + 20] = (v + 3);
                                indices[i + 21] = v + 1; indices[i + 22] = v; indices[i + 23] = (v + 3);
                                v += 8;
                                i += 24;
                                break;
                            default:
                                vertices[v] = new VertexPositionTexture(new Vector3(x + 1, y, z + 1), new Vector2(1.0f, 1.0f)); // Bottom
                                vertices[v + 1] = new VertexPositionTexture(new Vector3(x, y, z + 1), new Vector2(0.0f, 1.0f));
                                vertices[v + 2] = new VertexPositionTexture(new Vector3(x, y, z), new Vector2(0.0f, 0.0f));
                                vertices[v + 3] = new VertexPositionTexture(new Vector3(x + 1, y, z), new Vector2(1.0f, 0.0f));
                                indices[i] = v; indices[i + 1] = (v + 1); indices[i + 2] = (v + 2);
                                indices[i + 3] = (v + 3); indices[i + 4] = v; indices[i + 5] = (v + 2);
                                v += 4;
                                i += 6;
                                break;
                        }
                    }
                }
            }
            gp.Effect = MapEffect;
            gp.VertexBuffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New<VertexPositionTexture>(GraphicEngine.GraphicsDevice, vertices);
            gp.IndexBuffer = SharpDX.Toolkit.Graphics.Buffer.Index.New(GraphicEngine.GraphicsDevice, indices);
            gp.NumVertices = vertices.Length;
            gp.Texture = MapTexture;
            gp.VertexStride = VertexPositionTexture.Size;
            // Create an input layout from the vertices
            gp.InputLayout = VertexInputLayout.FromBuffer(0, (Buffer<VertexPositionTexture>)gp.VertexBuffer);
            return gp;
        }

        private static void SetNbVertices(GraphicProperty gp, Map map)
        {
            gp.NumVertices = 0;
            gp.NumIndices = 0;
            gp.NumTriangles = 0;
            for (int x = 0; x < map.SizeX; x++)
            {
                for (int y = 0; y < map.SizeY; y++)
                {
                    for (int z = 0; z < map.SizeZ; z++)
                    {
                        switch (map.MapCases[x, y, z])
                        {
                            case MapCase.Empty:
                                break;
                            case MapCase.Wall:
                                gp.NumVertices += 8;
                                gp.NumIndices += 24;
                                gp.NumTriangles += 8;
                                /*
                                gp.NumVertices += 16;
                                gp.NumIndices += 24;
                                gp.NumTriangles += 8;*/
                                break;
                            default:
                                gp.NumVertices += 4;
                                gp.NumIndices += 6;
                                gp.NumTriangles += 2;
                                break;

                        }
                    }
                }
            }
        }
    }
}
